﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web.Mvc;
using MvcContrib.Sorting;
using MvcContrib.UI.Grid;
using QDT.Common;
using QDT.Common.Data;
using QDT.Core;
using QDT.Core.Deals;
using QDT.Core.Members;
using QDT.Core.Projects;
using QDT.MVC.Security;
using QDT.Services.Assignments;
using QDT.Services.Deals;
using QDT.Services.Projects;
using QDT.Web.Admin.Code;
using QDT.Web.Admin.Models;
using System.Linq.Dynamic;

namespace QDT.Web.Admin.Controllers
{
    [SecurityModule(Name = "项目管理")]
    public class ProjectController : BaseController {

        private readonly IProjectService _projectService;
        private readonly IDealService _dealService;

        public ProjectController(IProjectService projectService, IDealService dealService)
        {
            _projectService = projectService;
            _dealService = dealService;
        }

        [SecurityNode(Name = "项目列表")]
        public ActionResult Index(int? page, GridSortOptions sort, int? projectId, string name, string username, DateTime? start, DateTime? end, int? agencyId, int? typeId, int? dealStatus, int? repayTime)
        {

            User user = null;

            if (!string.IsNullOrWhiteSpace(username))
            {
                user = DbProvider.D<User>().FirstOrDefault(x => x.UserName == username);
            }

            ViewData["ProjectTypes"] = DbProvider.D<ProjectType>().Where(x => !x.IsDelete).ToList();

            var filter = PredicateExtensionses.True<Project>();

            if (repayTime != null && repayTime != 0) filter = filter.And(x => x.RepayTime == repayTime);

            if (projectId != null && projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (!string.IsNullOrEmpty(name)) filter = filter.And(x => x.Name.Contains(name));

            if (typeId != null && typeId > 0) filter = filter.And(x => x.TypeID == typeId);

            if (user != null) filter = filter.And(x => x.UserID == user.ID);

            if (dealStatus != null) filter = filter.And(x => x.InnerStatus == dealStatus);

            if (start.HasValue) filter = filter.And(x => x.CreateTime >= start.Value);

            if (end.HasValue) filter = filter.And(x => x.CreateTime <= end.Value);

            if (agencyId.HasValue) filter = filter.And(x => x.Parent.AgencyId >= agencyId);

            const int pageSize = 20;

            var pageNumber = page ?? 1;

            if (sort.Column == null) sort.Column = "ID";

            ViewData["sort"] = sort;

            var deals = DbProvider.D<Project>().Where(filter.And(x => !x.IsDelete && !x.IsOffline)).OrderBy(sort.Column, sort.Direction == SortDirection.Descending);

            return View(deals.ToPagedList(pageNumber - 1, pageSize));

        }

        //[SecurityNode(Name = "易存宝列表")]
        public ActionResult Easy(int? page, GridSortOptions sort, int? projectId, string name, string username, DateTime? start, DateTime? end, int? agencyId, int? typeId, int? dealStatus, int? repayTime)
        {

            User user = null;

            if (!string.IsNullOrWhiteSpace(username))
            {
                user = DbProvider.D<User>().FirstOrDefault(x => x.UserName == username);
            }

            ViewData["ProjectTypes"] = DbProvider.D<ProjectType>().Where(x => !x.IsDelete).ToList();

            var filter = PredicateExtensionses.True<Project>();

            if (repayTime != null && repayTime != 0) filter = filter.And(x => x.RepayTime == repayTime);

            if (projectId != null && projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (!string.IsNullOrEmpty(name)) filter = filter.And(x => x.Name.Contains(name));

            if (typeId != null && typeId > 0) filter = filter.And(x => x.TypeID == typeId);

            if (user != null) filter = filter.And(x => x.UserID == user.ID);

            if (dealStatus != null) filter = filter.And(x => x.InnerStatus == dealStatus);

            if (start.HasValue) filter = filter.And(x => x.CreateTime >= start.Value);

            if (end.HasValue) filter = filter.And(x => x.CreateTime <= end.Value);

            if (agencyId.HasValue) filter = filter.And(x => x.Parent.AgencyId >= agencyId);

            const int pageSize = 20;

            var pageNumber = page ?? 1;

            if (sort.Column == null) sort.Column = "ID";

            ViewData["sort"] = sort;

            var deals = DbProvider.D<Project>().Where(filter.And(x => !x.IsDelete && x.IsOffline)).OrderBy(sort.Column, sort.Direction == SortDirection.Descending);

            return View(deals.ToPagedList(pageNumber - 1, pageSize));

        }

        [SecurityNode(Name = "项目回收站")]
        public ActionResult Trash(int? page, GridSortOptions sort, int? projectId, string name, string username, int? typeId, int? dealStatus)
        {
            User user = null;

            if (!string.IsNullOrWhiteSpace(username))
            {
                user = DbProvider.D<User>().FirstOrDefault(x => x.UserName == username);
            }

            var filter = PredicateExtensionses.True<Project>();

            if (projectId != null && projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (!string.IsNullOrEmpty(name)) filter = filter.And(x => x.Name.Contains(name));

            if (typeId != null && typeId != 0) filter = filter.And(x => x.TypeID == typeId);

            if (user != null) filter = filter.And(x => x.UserID == user.ID);

            if (dealStatus != null && dealStatus != 0) filter = filter.And(x => x.InnerStatus == dealStatus);

            const int pageSize = 20;
            var pageNumber = page ?? 1;
            if (sort.Column == null) sort.Column = "ID";
            ViewData["sort"] = sort;

            var deals = DbProvider.D<Project>().Where(filter.And(x => x.IsDelete)).OrderBy(sort.Column, sort.Direction == SortDirection.Descending);

            return View(deals.ToPagedList(pageNumber - 1, pageSize));

        }

        [SecurityNode(Name = "三日还款列表")]
        public ActionResult Three(int? page, GridSortOptions sort, int? projectId, string name, string username, int? typeId)
        {
            User user = null;

            if (!string.IsNullOrWhiteSpace(username))
            {
                user = DbProvider.D<User>().FirstOrDefault(x => x.UserName == username);
            }

            var types = DbProvider.D<ProjectType>().Where(x => !x.IsDelete).ToList();

            ViewData["ProjectTypes"] = types;

            var filter = PredicateExtensionses.True<Project>();

            if (projectId != null && projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (!string.IsNullOrEmpty(name)) filter = filter.And(x => x.Name.Contains(name));

            if (typeId != null && typeId > 0) filter = filter.And(x => x.TypeID == typeId);

            if (user != null) filter = filter.And(x => x.UserID == user.ID);

            const int pageSize = 20;

            var pageNumber = page ?? 1;

            if (sort.Column == null) sort.Column = "NextRepayTime";

            ViewData["sort"] = sort;

            var threeDay = DateTime.Now.Date.AddDays(2);
            const int intRepaying = (int)ProjectStatus.Repaying;

            var orderby = sort.Column + ",RepayStartTime" + " " + (sort.Direction == SortDirection.Descending ? "desc" : "asc");

            //var deals = DbProvider.D<Project>()
            //    .Where(filter.And(x => !x.IsDelete && x.InnerStatus == intRepaying))
            //    .OrderBy(orderby);
            var deals = DbProvider.D<Project>()
                .Where(filter.And(x => !x.IsDelete && x.InnerStatus == intRepaying && x.NextRepayTime != null && x.NextRepayTime.Value <= threeDay))
                .OrderBy(orderby);

            return View(deals.ToPagedList(pageNumber - 1, pageSize));
        }

        [SecurityNode(Name = "逾期还款列表")]
        public ActionResult OverTime(int? page, GridSortOptions sort, int? projectId, string name, string username, int? typeId)
        {
            User user = null;

            if (!string.IsNullOrWhiteSpace(username))
            {
                user = DbProvider.D<User>().FirstOrDefault(x => x.UserName == username);
            }

            var types = DbProvider.D<ProjectType>().Where(x => !x.IsDelete).ToList();

            ViewData["ProjectTypes"] = types;

            var filter = PredicateExtensionses.True<Project>();

            if (projectId != null && projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (!string.IsNullOrEmpty(name)) filter = filter.And(x => x.Name.Contains(name));

            if (typeId != null && typeId > 0) filter = filter.And(x => x.TypeID == typeId);

            if (user != null) filter = filter.And(x => x.UserID == user.ID);

            const int pageSize = 20;

            var pageNumber = page ?? 1;

            if (sort.Column == null) sort.Column = "ID";

            ViewData["sort"] = sort;

            var now = DateTime.Now.Date;
            const int intRepaying = (int)ProjectStatus.Repaying;

            var orderby = sort.Column + ",RepayStartTime" + " " + (sort.Direction == SortDirection.Descending ? "desc" : "asc");

            //var deals = DbProvider.D<Project>()
            //    .Where(filter.And(x => !x.IsDelete && x.InnerStatus == intRepaying))
            //    .OrderBy(orderby);
            var deals = DbProvider.D<Project>()
                .Where(filter.And(x => !x.IsDelete && x.InnerStatus == intRepaying && x.NextRepayTime != null && x.NextRepayTime.Value < now))
                .OrderBy(orderby);

            return View(deals.ToPagedList(pageNumber - 1, pageSize));
        }

        [SecurityNode(Name = "还款中列表")]
        public ActionResult Repaying(int? page, GridSortOptions sort, int? projectId, string name, string username, int? typeId, DateTime? time)
        {
            User user = null;

            if (!string.IsNullOrWhiteSpace(username))
            {
                user = DbProvider.D<User>().FirstOrDefault(x => x.UserName == username);
            }

            var types = DbProvider.D<ProjectType>().Where(x => !x.IsDelete).ToList();

            ViewData["ProjectTypes"] = types;

            var filter = PredicateExtensionses.True<Project>();

            if (projectId != null && projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (!string.IsNullOrEmpty(name)) filter = filter.And(x => x.Name.Contains(name));

            if (typeId != null && typeId > 0) filter = filter.And(x => x.TypeID == typeId);

            if (user != null) filter = filter.And(x => x.UserID == user.ID);

            if (time != null)
            {
                var start = time.Value.Date;
                var end = start.AddDays(1);
                filter = filter.And(x => x.NextRepayTime >= start && x.NextRepayTime < end);
            }

            const int pageSize = 20;

            var pageNumber = page ?? 1;

            if (sort.Column == null) sort.Column = "ID";

            ViewData["sort"] = sort;

            const int intRepaying = (int)ProjectStatus.Repaying;

            var orderby = sort.Column + ",RepayStartTime" + " " + (sort.Direction == SortDirection.Descending ? "desc" : "asc");

            var deals = DbProvider.D<Project>()
                .Where(filter.And(x => !x.IsDelete && x.InnerStatus == intRepaying))
                .OrderBy(orderby);

            return View(deals.ToPagedList(pageNumber - 1, pageSize));
        }

        [SecurityNode(Name = "返本金项目查询")]
        public ActionResult ThreePrincipal(int? page, DateTime? start, DateTime? end, int projectId = 0, int userid = 0)
        {
            const int pageSize = 20;
            var pageNumber = page ?? 1;
            var time = DateTime.Now.Date.AddMonths(3);

            var filter = PredicateExtensionses.True<Project>();

            if (!end.HasValue)
            {
                filter = filter.And(x => x.NextRepayTime < time);
            }
            else
            {
                if (end.Value < time) time = end.Value;
                filter = filter.And(x => x.NextRepayTime <= time);
            }

            if (start.HasValue) filter = filter.And(x => x.NextRepayTime >= start);

            if (projectId != 0) filter = filter.And(x => x.ID == projectId);

            if (userid != 0) filter = filter.And(x => x.UserID == userid);

            const int intRepaying = (int)ProjectStatus.Repaying;
            var projects = DbProvider.D<Project>()
                .Where(filter.And(x => x.InnerStatus == intRepaying && (x.RepayEndTime <= time)))
                .OrderBy(x=>x.NextRepayTime);
            if (projects.Count()!=0)
            {
                ViewData["RepayCount"] = projects.Count();
                ViewData["RepayAmount"] = projects.Sum(x => x.BorrowAmount).ToMoney();
            }
          
            return View(projects.ToPagedList(pageNumber - 1, pageSize));
        }

        [SecurityNode(Name = "还款详情")]
        public ActionResult Refund(int id)
        {

            var project = DbProvider.GetByID<Project>(id);

            if ((project.Status != ProjectStatus.Repaying && project.Status != ProjectStatus.Repaid)) return Error("项目不处于还款中");

            var scheme = _dealService.GetRepaymentScheme(id);

            ViewData["Project"] = project;

            return View(scheme);

        }

        [SecurityNode(Name = "添加项目")]
        public ActionResult AddProject(int ID = 0)
        {
            var types = DbProvider.D<ProjectType>().Where(x => !x.IsDelete && x.IsEffect).ToList();
            var agencys = DbProvider.D<ProjectAgency>().ToList();

            var extendFeild = DbProvider.D<ProjectFeild>().Where(x=>x.IsEffect).ToList();

            var extend = new Dictionary<int, IList<ProjectFeild>>();

            extendFeild.Each(o =>
                                 {
                                     if (!extend.ContainsKey(o.TypeID)) extend.Add(o.TypeID, new List<ProjectFeild>());
                                     extend[o.TypeID].Add(o);
                                 });

            ViewData["ProjectTypes"] = types;
            ViewData["ProjectAgencys"] = agencys;
            ViewData["Extend"] = extend;
            ViewBag.LoanId = ID;

            return View();
        }

        [HttpPost]
        [ValidateInput(false)]
        [SecurityNode(Name = "添加项目操作")]
        public ActionResult PostAddProject(ProjectModel model)
        {
            if (!ModelState.IsValid) return Error();

            var parentProject = DbProvider.GetByID<ParentProject>(model.LoanId);

            if (model.BorrowAmount <= 0) return Error("借款金额不能小于0");

            if (model.MinLoanMoney <= 0 || model.MinLoanMoney > model.BorrowAmount) return Error("最小投资额度不能小于0，大于总借款金额");

            if (model.MaxLoanMoney <= 0 || model.MaxLoanMoney > model.BorrowAmount) return Error("最大投资额度不能小于0，大于总借款金额");

            if (parentProject.RepayTime <= 0) return Error("借款期限不能小于0");

            if (parentProject.Rate <= 0) return Error("利率不能小于0");

            var type = DbProvider.GetByID<ProjectType>(parentProject.TypeId);

            if (type == null) return Error("项目类型不存在");

            var project = new Project(parentProject, model.Name, model.SubName, model.BorrowAmount,model.MinLoanMoney, model.MaxLoanMoney)
                           {
                               IsOffline = model.IsOffline,
                               AssignAble = model.AssignAble
                           };

            DbProvider.Add(project);

            Logs("添加项目： {0}", project.Name);

            return Success("添加成功");
        }

        [SecurityNode(Name = "编辑项目")]
        public ActionResult EditProject(int id)
        {

            var project = DbProvider.GetByID<Project>(id);

            if (project == null) return Error("项目不存在");

            var types = DbProvider.D<ProjectType>().Where(x => !x.IsDelete && x.IsEffect).ToList();
            var agencys = DbProvider.D<ProjectAgency>().ToList();

            var extendFeild = DbProvider.D<ProjectFeild>().Where(x => x.IsEffect).ToList();

            var extend = new Dictionary<int, IList<ProjectFeild>>();

            extendFeild.Each(o =>
            {
                if (!extend.ContainsKey(o.TypeID)) extend.Add(o.TypeID, new List<ProjectFeild>());
                extend[o.TypeID].Add(o);
            });

            //var payments = AlgorithmInfo.GetAlgorithmInfos();

            ViewData["ProjectTypes"] = types;
            ViewData["ProjectAgencys"] = agencys;
            ViewData["Extend"] = extend;
            //ViewData["Payments"] = payments;

            return View(project);
        }

        [HttpPost]
        [SecurityNode(Name = "编辑项目操作")]
        [ValidateInput(false)]
        public ActionResult PostEditDeal(ProjectModel model)
        {
            var project = DbProvider.GetByID<Project>(model.Id);
            project.AssignAble = model.AssignAble;
            project.MaxLoanMoney = model.MaxLoanMoney;
            project.Name = model.Name;
            project.SubName = model.SubName;
            project.IsOffline = model.IsOffline;
            DbProvider.SaveChanges();
            return Success("编辑成功");
        }

        [HttpPost]
        [SecurityNode(Name = "删除项目")]
        public ActionResult Delete(int[] id)
        {
            _projectService.DeleteProject(id);
            return Success("删除成功");
        }

        [HttpPost]
        [SecurityNode(Name = "恢复删除")]
        public ActionResult Restore(int[] id)
        {
            _projectService.RestoreProject(id);
            return Success("恢复成功");
        }

        [HttpPost]
        [SecurityNode(Name = "彻底删除")]
        public ActionResult ForeverDel(int[] id)
        {
            _projectService.ForeverDeleteProject(id);
            return Success("彻底删除成功");
        }

        [SecurityNode(Name = "投资列表")]
        public PartialViewResult ShowDetail(int id)
        {

            var project = DbProvider.GetByID<Project>(id);

            var credits = DbProvider.D<Credit>().Where(x => x.ProjectID == id).ToList().Where(x=>x.IsEffect);

            var model=new ProjectDetail()
            {
                Project = project,
                Credits = credits.ToList()
            };

            return PartialView(model);

        }

        [SecurityNode(Name = "编辑状态")]
        public ActionResult ChangeStatus(int id)
        {
            var project = DbProvider.GetByID<Project>(id);
            return PartialView(project);
        }

        [SecurityNode(Name = "编辑状态操作")]
        public ActionResult PostChange(int id, ProjectStatus status, DateTime? startTime, DateTime? repayTime)
        {
            if (status == ProjectStatus.Wait)
            {
                if (startTime == null || startTime.Value < DateTime.Now.AddMinutes(-10)) return Error("时间日期输入错误！");
                _projectService.Release(id, startTime.Value);
            }
            if (status == ProjectStatus.Full)
            {
                if (repayTime == null) return Error("时间日期输入错误！");
                _projectService.Paying(id, repayTime.Value);
            }
            return Success("操作成功！");
        }

        [SecurityNode(Name = "还款操作")]
        public ActionResult PostRefund(int id, int stage)
        {
            
            _dealService.Refund(id,stage, AdminUser.ID);

            Logs("偿还利息,标:{0},第{1}期", id, stage);
            return Success("操作成功");
        }

        [SecurityNode(Name = "上传合同")]
        public ActionResult Agreement(int id)
        {
            var project = DbProvider.GetByID<Project>(id);
            if (project.Status != ProjectStatus.Repaying)
            {
                return Success("不是还款中的项目不能生成合同");
            }
            if (string.IsNullOrWhiteSpace(project.AgreementLink))
            {
                ThreadPool.QueueUserWorkItem(state => new PDFSealToo().SeaProjectAgreement(id));
                return Success("正在生成~");
            }
            return View(project);
        }

        [SecurityNode(Name = "上传合同")]
        public ActionResult UploadAgreement(int pid, string agreement)
        {
            var project = DbProvider.GetByID<Project>(pid);
            project.AgreementLink = agreement;
            DbProvider.SaveChanges();
            return Success("上传成功");
        }

        public ActionResult Ponit(int pid)
        {
//            ThreadPool.QueueUserWorkItem(state => new PointHelper().ProjectPointSta(pid));
            return Success("操作成功");
        }
        public ActionResult Bad(int id)
        {
            _dealService.Bad(id);
            return Success("操作成功");
        }
        public ActionResult AppBidList(int? page, GridSortOptions sort, string username, DateTime? createTime)
        {
            var filter = PredicateExtensionses.True<Credit>();

            if (!string.IsNullOrWhiteSpace(username)) filter = filter.And(x => x.UserName.Contains(username));

            if (createTime.HasValue)
            {
                var startTime = ((DateTime)createTime).Date;
                var emdTime = startTime.AddDays(1);
                filter = filter.And(x => x.CreateTime >= startTime && x.CreateTime < emdTime);
            }

            const int pageSize = 20;

            var pageNumber = page ?? 1;

            if (sort.Column == null) sort.Column = "ID";

            ViewData["sort"] = sort;

            var sources = DbProvider.D<Credit>().Where(filter.And(x => x.Client != 0)).OrderBy(sort.Column, sort.Direction == SortDirection.Descending);

            return View(sources.ToPagedList(pageNumber - 1, pageSize));

        }

    }
}
